home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / DOSSIG.C < prev    next >
C/C++ Source or Header  |  1992-05-28  |  24KB  |  906 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/dossig.c,v 1.3 1992/05/28 19:34:43 jinx Exp $
  4.  
  5. Copyright (c) 1992 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. #include "msdos.h"
  36. #include "config.h"
  37. #include <signal.h>
  38. #include <int.h>
  39. #include "ossig.h"
  40. #include "osctty.h"
  41. #include "ostty.h"
  42. #include "critsec.h"
  43. #include <bios.h>
  44. #include "dossys.h"
  45. #include "dosexcp.h"
  46. #include "doskbd.h"
  47.  
  48. /* Signal Manipulation */
  49.  
  50. static Tsignal_handler
  51. DEFUN (current_handler, (signo), int signo)
  52. {
  53.   Tsignal_handler result = (DOS_signal (signo, SIG_IGN));
  54.   if (result != SIG_IGN)
  55.     DOS_signal (signo, result);
  56.   return (result);
  57. }
  58.  
  59. #define INSTALL_HANDLER DOS_signal
  60. #define NEED_HANDLER_TRANSACTION
  61.  
  62. #define ENTER_HANDLER(signo)
  63. #define ABORT_HANDLER DOS_signal
  64. #define EXIT_HANDLER DOS_signal
  65.  
  66. /* These could be implemented, at least under DPMI by examining
  67.    and setting the virtual interrupt state.
  68.  */
  69.  
  70. void
  71. DEFUN_VOID (preserve_signal_mask)
  72. {
  73. }
  74.  
  75. void
  76. DEFUN_VOID (block_signals)
  77. {
  78. }
  79.  
  80. void
  81. DEFUN_VOID (unblock_signals)
  82. {
  83. }
  84.  
  85. /* Signal Descriptors */
  86.  
  87. enum dfl_action { dfl_terminate, dfl_ignore, dfl_stop };
  88.  
  89. struct signal_descriptor
  90. {
  91.   int signo;
  92.   CONST char * name;
  93.   enum dfl_action action;
  94.   int flags;
  95. };
  96.  
  97. /* `flags' bits */
  98. #define NOIGNORE 1
  99. #define NOBLOCK 2
  100. #define NOCATCH 4
  101. #define CORE_DUMP 8
  102.  
  103. static struct signal_descriptor * signal_descriptors;
  104. static unsigned int signal_descriptors_length;
  105. static unsigned int signal_descriptors_limit;
  106.  
  107. static void
  108. DEFUN (defsignal, (signo, name, action, flags),
  109.        int signo AND
  110.        CONST char * name AND
  111.        enum dfl_action action AND
  112.        int flags)
  113. {
  114.   if (signo == 0)
  115.     return;
  116.   if (signal_descriptors_length == signal_descriptors_limit)
  117.     {
  118.       signal_descriptors_limit += 8;
  119.       signal_descriptors =
  120.     (DOS_realloc (signal_descriptors,
  121.              (signal_descriptors_limit *
  122.               (sizeof (struct signal_descriptor)))));
  123.       if (signal_descriptors == 0)
  124.     {
  125.       fprintf (stderr, "\nUnable to grow signal definitions table.\n");
  126.       fflush (stderr);
  127.       termination_init_error ();
  128.     }
  129.     }
  130.   {
  131.     struct signal_descriptor * sd =
  132.       (signal_descriptors + (signal_descriptors_length++));
  133.     (sd -> signo) = signo;
  134.     (sd -> name) = name;
  135.     (sd -> action) = action;
  136.     (sd -> flags) = flags;
  137.   }
  138. }
  139.  
  140. static struct signal_descriptor *
  141. DEFUN (find_signal_descriptor, (signo), int signo)
  142. {
  143.   struct signal_descriptor * scan = signal_descriptors;
  144.   struct signal_descriptor * end = (scan + signal_descriptors_length);
  145.   for (; (scan < end); scan += 1)
  146.     if ((scan -> signo) == signo)
  147.       return (scan);
  148.   return (0);
  149. }
  150.  
  151. CONST char *
  152. DEFUN (find_signal_name, (signo), int signo)
  153. {
  154.   static char buffer [32];
  155.   struct signal_descriptor * descriptor = (find_signal_descriptor (signo));
  156.   if (descriptor != 0)
  157.     return (descriptor -> name);
  158.   sprintf (buffer, "unknown signal %d", signo);
  159.   return ((CONST char *) buffer);
  160. }
  161.  
  162. #define OS_SPECIFIC_SIGNALS()
  163.  
  164. #if (SIGABRT == SIGIOT)
  165. #undef SIGABRT
  166. #define SIGABRT 0
  167. #endif
  168.  
  169. static void
  170. DEFUN_VOID (initialize_signal_descriptors)
  171. {
  172.   signal_descriptors_length = 0;
  173.   signal_descriptors_limit = 32;
  174.   signal_descriptors =
  175.     (DOS_malloc (signal_descriptors_limit *
  176.          (sizeof (struct signal_descriptor))));
  177.   if (signal_descriptors == 0)
  178.     {
  179.       fprintf (stderr, "\nUnable to allocate signal definitions table.\n");
  180.       fflush (stderr);
  181.       termination_init_error ();
  182.     }
  183.  
  184.   defsignal (SIGINT, "SIGINT",        dfl_terminate,    0);
  185.   defsignal (SIGILL, "SIGILL",        dfl_terminate,    CORE_DUMP);
  186.   defsignal (SIGFPE, "SIGFPE",        dfl_terminate,    CORE_DUMP);
  187.   defsignal (SIGSEGV, "SIGSEGV",    dfl_terminate,    CORE_DUMP);
  188.   defsignal (SIGTERM, "SIGTERM",    dfl_terminate,    0);
  189.   defsignal (SIGABRT, "SIGABRT",    dfl_terminate,    CORE_DUMP);
  190.  
  191.   OS_SPECIFIC_SIGNALS ();
  192. }
  193.  
  194. /* Signal Handlers */
  195.  
  196. struct handler_record
  197. {
  198.   int signo;
  199.   Tsignal_handler handler;
  200. };
  201.  
  202. #define DEFUN_STD_HANDLER(name, statement)                \
  203. static Tsignal_handler_result                        \
  204. DEFUN (name, (signo), int signo)                    \
  205. {                                    \
  206.   int STD_HANDLER_abortp;                        \
  207.   ENTER_HANDLER (signo);                        \
  208.   STD_HANDLER_abortp = (enter_interruption_extent ());            \
  209.   transaction_begin ();                            \
  210.   {                                    \
  211.     struct handler_record * record =                    \
  212.       (dstack_alloc (sizeof (struct handler_record)));            \
  213.     (record -> signo) = signo;                        \
  214.     (record -> handler) = 0;                        \
  215.     transaction_record_action (tat_abort, ta_abort_handler, record);    \
  216.   }                                    \
  217.   statement;                                \
  218.   if (STD_HANDLER_abortp)                        \
  219.     {                                    \
  220.       transaction_abort ();                        \
  221.       exit_interruption_extent ();                    \
  222.     }                                    \
  223.   transaction_commit ();                        \
  224.   EXIT_HANDLER (signo, name);                        \
  225.   SIGNAL_HANDLER_RETURN ();                        \
  226. }
  227.  
  228. static void
  229. DEFUN (ta_abort_handler, (ap), PTR ap)
  230. {
  231.   ABORT_HANDLER ((((struct handler_record *) ap) -> signo),
  232.          (((struct handler_record *) ap) -> handler));
  233. }
  234.  
  235. #define CONTROL_B_INTERRUPT_CHAR 'B'
  236. #define CONTROL_G_INTERRUPT_CHAR 'G'
  237. #define CONTROL_U_INTERRUPT_CHAR 'U'
  238. #define CONTROL_X_INTERRUPT_CHAR 'X'
  239. #define GENERAL_INTERRUPT_CHAR     '!'
  240. #define NO_INTERRUPT_CHAR     '0'
  241.  
  242. static void
  243. DEFUN (echo_keyboard_interrupt, (c, dc), cc_t c AND cc_t dc)
  244. {
  245.   c &= 0177;
  246.   if (c == ALERT_CHAR)
  247.     putc (c, stdout);
  248.   else if (c < '\040')
  249.     {
  250.       putc ('^', stdout);
  251.       putc ((c + '@'), stdout);
  252.     }
  253.   else if (c == '\177')
  254.     fputs ("^?", stdout);
  255.   else
  256.     putc (c, stdout);
  257.   fflush (stdout);
  258. }
  259.  
  260. DEFUN_STD_HANDLER (sighnd_control_g,
  261.   { 
  262.     tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  263.   })
  264.     
  265. DEFUN_STD_HANDLER (sighnd_control_c,
  266.   { 
  267.     tty_set_next_interrupt_char (GENERAL_INTERRUPT_CHAR);
  268.   })
  269.  
  270. /* Keyboard interrupt */
  271. #define KB_INT_TABLE_SIZE        ((256) + 1)
  272.  
  273. #define CONTROL_B            '\002'
  274. #define CONTROL_C            '\003'
  275. #define CONTROL_G            '\007'
  276. #define CONTROL_U            '\025'
  277. #define CONTROL_X            '\030'
  278.  
  279. #define CONTROL_B_ENABLE        (0x1)
  280. #define CONTROL_G_ENABLE        (0x2)
  281. #define CONTROL_U_ENABLE        (0x4)
  282. #define CONTROL_X_ENABLE        (0x8)
  283. #define GENERAL_INTERRUPT_ENABLE    (0x10)
  284.  
  285. /* This is a table and also a null terminated string. */
  286. unsigned char keyboard_interrupt_table[KB_INT_TABLE_SIZE];
  287. static unsigned char keyboard_interrupt_enables;
  288.  
  289. void
  290. DEFUN (OS_ctty_get_interrupt_enables, (mask), Tinterrupt_enables * mask)
  291. {
  292.   *mask = (Tinterrupt_enables) keyboard_interrupt_enables;
  293.   return;
  294. }
  295.  
  296. void 
  297. DEFUN (OS_ctty_set_interrupt_enables, (mask), Tinterrupt_enables * mask)
  298. {
  299.   keyboard_interrupt_enables = *mask;
  300.   return;
  301. }
  302.  
  303. /* This is a temporary kludge. */
  304.  
  305. #define NUM_INT_CHANNELS 5
  306. static cc_t int_chars[NUM_INT_CHANNELS];
  307. static cc_t int_handlers[NUM_INT_CHANNELS];
  308.  
  309. static void
  310. DEFUN_VOID (update_interrupt_characters)
  311. {
  312.   int i;
  313.  
  314.   for (i = 0; i < KB_INT_TABLE_SIZE; i++)
  315.     keyboard_interrupt_table[i] = NO_INTERRUPT_CHAR;
  316.  
  317.   for (i = 0; i < NUM_INT_CHANNELS; i++)
  318.   {
  319.     unsigned char handler;
  320.  
  321.     switch (int_handlers[i])
  322.     {
  323.       case interrupt_handler_control_b:
  324.         handler = CONTROL_B_INTERRUPT_CHAR;
  325.     break;
  326.  
  327.       case interrupt_handler_control_g:
  328.         handler = CONTROL_G_INTERRUPT_CHAR;
  329.     break;
  330.  
  331.       case interrupt_handler_control_u:
  332.         handler = CONTROL_U_INTERRUPT_CHAR;
  333.     break;
  334.  
  335.       case interrupt_handler_control_x:
  336.         handler = CONTROL_X_INTERRUPT_CHAR;
  337.     break;
  338.  
  339.       case interrupt_handler_interactive:
  340.         handler = GENERAL_INTERRUPT_CHAR;
  341.     break;
  342.  
  343.       default:
  344.         handler = NO_INTERRUPT_CHAR;
  345.     break;
  346.     }
  347.     keyboard_interrupt_table[(int) (int_chars[i])] = handler;
  348.   }
  349.   return;
  350. }
  351.  
  352. unsigned int
  353. DEFUN_VOID (OS_ctty_num_int_chars)
  354. {
  355.   return (NUM_INT_CHANNELS);
  356. }
  357.  
  358. cc_t *
  359. DEFUN_VOID (OS_ctty_get_int_chars)
  360. {
  361.   return (&int_chars[0]);
  362. }
  363.  
  364. void
  365. DEFUN (OS_ctty_set_int_chars, (new_int_chars), cc_t * new_int_chars)
  366. {
  367.   int i;
  368.  
  369.   for (i = 0; i < NUM_INT_CHANNELS; i++)
  370.     int_chars[i] = new_int_chars[i];
  371.   update_interrupt_characters ();
  372.   return;
  373. }
  374.  
  375. cc_t *
  376. DEFUN_VOID (OS_ctty_get_int_char_handlers)
  377. {
  378.   return (&int_handlers[0]);
  379. }
  380.  
  381. void
  382. DEFUN (OS_ctty_set_int_char_handlers, (new_int_handlers),
  383.        cc_t * new_int_handlers)
  384. {
  385.   int i;
  386.  
  387.   for (i = 0; i < NUM_INT_CHANNELS; i++)
  388.     int_handlers[i] = new_int_handlers[i];
  389.   update_interrupt_characters ();
  390.   return;
  391. }
  392.  
  393. void
  394. DEFUN_VOID (initialize_keyboard_interrupt_table)
  395. {
  396.   /* Set up default interrupt characters */
  397.   int_chars[0] = CONTROL_B;
  398.   int_handlers[0] = ((unsigned char) interrupt_handler_control_b);
  399.   int_chars[1] = CONTROL_G;
  400.   int_handlers[1] = ((unsigned char) interrupt_handler_control_g);
  401.   int_chars[2] = CONTROL_U;
  402.   int_handlers[2] = ((unsigned char) interrupt_handler_control_u);
  403.   int_chars[3] = CONTROL_X;
  404.   int_handlers[3] = ((unsigned char) interrupt_handler_control_x);
  405.   int_chars[4] = CONTROL_C;
  406.   int_handlers[4] = ((unsigned char) interrupt_handler_interactive);
  407.   update_interrupt_characters ();
  408.   keyboard_interrupt_enables =
  409.     (CONTROL_B_ENABLE | CONTROL_G_ENABLE | CONTROL_U_ENABLE |
  410.      CONTROL_X_ENABLE | GENERAL_INTERRUPT_ENABLE);
  411.   return;
  412. }
  413.  
  414. int
  415. DEFUN (signal_keyboard_character_interrupt, (c), unsigned char c)
  416. {
  417.   if ((c >= 0) && (c < KB_INT_TABLE_SIZE))
  418.   { int interrupt_char = keyboard_interrupt_table[c];
  419.     int interrupt_p;
  420.  
  421. #define Request_Interrupt_If_Enabled(mask)            \
  422.   ( interrupt_p =                        \
  423.       ( (keyboard_interrupt_enables&(mask))            \
  424.     ? tty_set_next_interrupt_char (interrupt_char), 1 : 0 ))
  425.     
  426.     switch (interrupt_char)
  427.     { 
  428.       case CONTROL_B_INTERRUPT_CHAR:
  429.     Request_Interrupt_If_Enabled(CONTROL_B_ENABLE); break;
  430.       case CONTROL_G_INTERRUPT_CHAR:
  431.     Request_Interrupt_If_Enabled(CONTROL_G_ENABLE); break;
  432.       case CONTROL_U_INTERRUPT_CHAR:
  433.     Request_Interrupt_If_Enabled(CONTROL_U_ENABLE); break;
  434.       case CONTROL_X_INTERRUPT_CHAR:
  435.     Request_Interrupt_If_Enabled(CONTROL_X_ENABLE); break;
  436.       case GENERAL_INTERRUPT_CHAR:
  437.     Request_Interrupt_If_Enabled(GENERAL_INTERRUPT_ENABLE); break;
  438.       default:
  439.     interrupt_p = 0;
  440.     }
  441.     return interrupt_p;
  442.   }
  443.   return 0;
  444. }      
  445.  
  446.  
  447. static void
  448. DEFUN_VOID (print_interrupt_help)
  449.   console_write_string("\nInterrupt Choices are:\n");
  450.   console_write_string("C-G interrupt: G, g, ^G (abort to top level)\n");
  451.   console_write_string("C-X interrupt: X, x, ^x (abort)\n");
  452.   console_write_string("C-B interrupt: B, b, ^B (break)\n");
  453.   console_write_string("C-U interrupt: U, u, ^U (up)\n");
  454.   console_write_string("Quit scheme:   Q, q\n");
  455.   console_write_string("Print help:    ?");
  456.  
  457.   return;
  458. }
  459.   
  460. cc_t
  461. DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char)
  462. {
  463.   if ((int_char == CONTROL_B_INTERRUPT_CHAR) ||
  464.       (int_char == CONTROL_G_INTERRUPT_CHAR) ||
  465.       (int_char == CONTROL_X_INTERRUPT_CHAR) ||
  466.       (int_char == CONTROL_U_INTERRUPT_CHAR) )
  467.     return int_char;
  468.   
  469.   while (1)
  470.   { unsigned char response;
  471.  
  472.     console_write_string
  473.       ("\nKeyboard interrupt, type character (? for help): ");
  474.     
  475.     response = (dos_get_keyboard_character ());
  476.     dos_console_write_character (response);
  477.     
  478.     switch (response)
  479.     {
  480.       case 'b':
  481.       case 'B':
  482.       case CONTROL_B:
  483.     return CONTROL_B_INTERRUPT_CHAR;
  484.  
  485.       case 'g':
  486.       case 'G':
  487.       case CONTROL_G:
  488.     return CONTROL_G_INTERRUPT_CHAR;
  489.  
  490.       case 'q':
  491.       case 'Q':
  492.       {
  493.     console_write_string ("\nTerminate scheme (y or n)? ");
  494.     response = (dos_get_keyboard_character ());
  495.     dos_console_write_character (response);
  496.     if ((response == 'y') || (response == 'Y'))
  497.     {
  498.       console_write_string ("\n");
  499.       termination_normal (0);
  500.     }
  501.     print_interrupt_help ();
  502.     break;
  503.       }
  504.  
  505.       case 'u':
  506.       case 'U':
  507.       case CONTROL_U:
  508.     return CONTROL_U_INTERRUPT_CHAR;
  509.  
  510.       case 'x':
  511.       case 'X':
  512.       case CONTROL_X:
  513.     return CONTROL_X_INTERRUPT_CHAR;
  514.  
  515.       case '?':
  516.     print_interrupt_help ();
  517.     break;
  518.  
  519.       default:
  520.       {
  521.     char temp[128];
  522.  
  523.     sprintf(temp, "\nIllegal interrupt character: [%c]", response);
  524.     console_write_string (temp);
  525.     print_interrupt_help ();
  526.     break;
  527.       }
  528.     } /* End CASE */
  529.  }    /* End WHILE */
  530. }
  531.   
  532. void
  533. DEFUN (stop_signal_default, (signo), int signo)
  534. {
  535.   return;
  536. }
  537.  
  538. void EXFUN ((*stop_signal_hook), (int signo));
  539.  
  540. #define IF_POSIX_SIGNALS(code) do {} while (0)
  541.  
  542. DEFUN_STD_HANDLER (sighnd_stop, {})
  543.  
  544. void
  545. DEFUN_VOID (OS_restartable_exit)
  546. {
  547.   stop_signal_default (SIGTSTP);
  548. }
  549.  
  550.  
  551. #ifdef HAVE_ITIMER
  552.  
  553. DEFUN_STD_HANDLER (sighnd_timer,
  554.   {
  555.     request_timer_interrupt ();
  556.   })
  557.  
  558. #else /* not HAVE_ITIMER */
  559.  
  560. extern void EXFUN (reschedule_alarm, (void));
  561.  
  562. DEFUN_STD_HANDLER (sighnd_timer,
  563.   {
  564.     /* reschedule_alarm ();
  565.        request_timer_interrupt ();
  566.      */
  567.   })
  568.  
  569. #endif /* HAVE_ITIMER */
  570.  
  571. DEFUN_STD_HANDLER (sighnd_save_then_terminate,
  572.   (request_suspend_interrupt ()))
  573.  
  574. #ifndef SIGNUP
  575. #define SIGHUP 999
  576. #endif
  577.  
  578. DEFUN_STD_HANDLER (sighnd_terminate,
  579.   (termination_signal
  580.    ((! (option_emacs_subprocess && (signo == SIGHUP)))
  581.     ? (find_signal_name (signo))
  582.     : 0)))
  583.  
  584. #define VOID ((struct sigcontext *) 0)
  585.  
  586. DEFUN_STD_HANDLER (sighnd_fpe,
  587.   {
  588.     if (executing_scheme_primitive_p ())
  589.       error_floating_point_exception ();
  590.     trap_handler ("floating-point exception signal", signo, VOID, VOID);
  591.   })
  592.  
  593. DEFUN_STD_HANDLER (sighnd_hardware_trap,
  594.   (trap_handler ("hardware fault signal", signo, VOID, VOID)))
  595.  
  596. DEFUN_STD_HANDLER (sighnd_software_trap,
  597.   (trap_handler ("system software fault signal", signo, VOID, VOID)))
  598.  
  599.  
  600. /* When a child process terminates, it becomes a zombie until its
  601.    parent process calls one of the wait() routines to obtain the
  602.    child's termination status.  The SIGCHLD handler must always call
  603.    wait() or waitpid() to permit the child process's resources to be
  604.    freed. */
  605.  
  606. /* On systems with waitpid() (i.e. those that support WNOHANG) we must
  607.    loop until there are no more processes, because some of those
  608.    systems may deliver only one SIGCHLD when more than one child
  609.    terminates.  Systems without waitpid() (e.g. _SYSV) typically
  610.    provide queuing of SIGCHLD such that one SIGCHLD is delivered for
  611.    every child that terminates.  Systems that provide neither
  612.    waitpid() nor queuing are so losing that we can't win, in which
  613.    case we just hope that child terminations don't happen too close to
  614.    one another to cause problems. */
  615.  
  616. void EXFUN ((*subprocess_death_hook), (pid_t pid, wait_status_t * status));
  617.  
  618. #define WAITPID(status) (DOS_wait (status))
  619. #define BREAK break
  620.  
  621. DEFUN_STD_HANDLER (sighnd_dead_subprocess,
  622.   {
  623.   })
  624.  
  625. /* PC specific low-level interrupt hooks */
  626. /* Control-Break Interrupt */
  627. int
  628. DEFUN (control_break_handler, (pd), struct INT_DATA *pd)
  629. {
  630.   tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  631.   return INTERRUPT_RETURN;
  632. }
  633.  
  634. /* Interval timer */
  635.  
  636. /* Scheme timer emulation; DOS does not have an ITIMER like unix. */
  637. /* Zero means timer is not set. */
  638.  
  639. volatile unsigned long scm_itimer_counter = 0;
  640. volatile unsigned long scm_itimer_reload = 0;
  641.  
  642. int 
  643. DEFUN (bios_timer_handler, (pd), struct INT_DATA *pd)
  644.   if (scm_itimer_reload != 0)
  645.   { if (--scm_itimer_counter == 0)
  646.     { 
  647.       scm_itimer_counter = scm_itimer_reload;
  648.       request_timer_interrupt();
  649.     }
  650.   }
  651.   return (INTERRUPT_CHAIN_NEXT);
  652. }
  653.  
  654. static Boolean
  655.   dos_interrupts_initialized_p = false,
  656.   ctrl_c_check_flag = true;
  657.  
  658. dos_boolean DOS_keyboard_intercepted_p = false;
  659.  
  660. #define NUM_DOS_INTVECT        (MAX_DOS_INTVECT + 1)
  661. #define NUM_DOS_HANDLERS    (NUM_DOS_INTVECT + NUM_DOS_EXCP)
  662. static int EXFUN ((* (dos_interrupt_restoration[NUM_DOS_HANDLERS])), 
  663.                   (unsigned));
  664.  
  665. static void
  666. DEFUN (dos_record_interrupt_interception, (intno, restorer),
  667.        unsigned intno AND int ((*restorer) (unsigned)))
  668. {
  669.   dos_interrupt_restoration[intno] = restorer;
  670.   return;
  671. }
  672.  
  673. static int
  674. DEFUN (scm_int_restore, (iv), unsigned iv)
  675. {
  676.   int_restore (iv);
  677.   return (DOS_SUCCESS);        /* A big lie. */
  678. }
  679.  
  680. static int 
  681. DEFUN (scm_int_intercept, (iv, proc, stack),
  682.        unsigned iv AND int (*proc)(struct INT_DATA *) AND unsigned stack)
  683. {
  684.   if ((int_intercept (iv, proc, stack)) != 0)
  685.     return (DOS_FAILURE);
  686.     
  687.   dos_record_interrupt_interception (iv, scm_int_restore);
  688.   return (DOS_SUCCESS);
  689. }
  690.  
  691. static void
  692. DEFUN_VOID (DOS_initialize_interrupts)
  693. {
  694.   int iv;
  695.   
  696.   ctrl_c_check_flag = (dos_set_ctrl_c_check_flag (0));
  697.   
  698.   for (iv = (NUM_DOS_HANDLERS - 1); iv >= 0; iv--)
  699.     dos_interrupt_restoration[iv] = ((int (*) (unsigned)) NULL);
  700.  
  701.   dos_interrupts_initialized_p = true;
  702.   return;
  703.  
  704. static char i386_exceptions_to_handle[] =
  705. {
  706.   DOS_EXCP_Integer_divide_by_zero,
  707.   DOS_EXCP_Debug_exception,
  708.   DOS_EXCP_Breakpoint,
  709.   DOS_EXCP_Integer_overflow,
  710.   DOS_EXCP_Bounds_check,
  711.   DOS_EXCP_Invalid_opcode,
  712.   DOS_EXCP_Numeric_co_processor_not_available,
  713.   DOS_EXCP_Numeric_co_processor_segment_overrun,
  714.   DOS_EXCP_Invalid_TSS,
  715.   DOS_EXCP_Segment_not_present,
  716.   DOS_EXCP_Stack_exception,
  717.   DOS_EXCP_General_protection,
  718.   DOS_EXCP_Page_Fault,
  719.   DOS_EXCP_Floating_point_exception,
  720.   DOS_EXCP_Alignment_check,
  721.   DOS_INVALID_TRAP
  722. };
  723.  
  724. static short old_excp_handler_cs[NUM_DOS_EXCP];
  725. static unsigned old_excp_handler_eip[NUM_DOS_EXCP];
  726. static void * stack_exception_fault_stack = ((void *) NULL);
  727.  
  728. #define STACK_EXCEPTION_STACK_SIZE    2048
  729.  
  730. static int
  731. DEFUN (DPMI_restore_handler, (iv), unsigned iv)
  732. {
  733.   unsigned excp = (iv - NUM_DOS_INTVECT);
  734.  
  735.   if ((DPMI_restore_exception_handler (excp,
  736.                        old_excp_handler_cs[excp],
  737.                        old_excp_handler_eip[excp]))
  738.       != DOS_SUCCESS)
  739.     return (DOS_FAILURE);
  740.   if (excp == DOS_EXCP_Stack_exception)
  741.   {
  742.     free (stack_exception_fault_stack);
  743.     stack_exception_fault_stack = ((void *) NULL);
  744.   }
  745.   return (DOS_SUCCESS);
  746. }
  747.  
  748. static void
  749. DEFUN (exception_handler, (trapno, trapcode, scp),
  750.        unsigned trapno AND unsigned trapcode AND struct sigcontext * scp)
  751. {
  752.   trap_handler ("hardware exception", ((int) trapno), trapcode, scp);
  753.   /*NOTREACHED*/
  754. }
  755.  
  756. static void
  757. DEFUN_VOID (DPMI_install_exception_handlers)
  758. {
  759.   int i;
  760.  
  761.   for (i = 0; dos_true ; i++)
  762.   {
  763.     int excp = ((int) i386_exceptions_to_handle[i]);
  764.  
  765.     if (excp == DOS_INVALID_TRAP)
  766.       break;
  767.     if ((DPMI_get_exception_vector (((unsigned) excp),
  768.                     & old_excp_handler_cs[excp],
  769.                     & old_excp_handler_eip[excp]))
  770.     != DOS_SUCCESS)
  771.       continue;
  772.     if (excp == DOS_EXCP_Stack_exception)
  773.     {
  774.       char * stack;
  775.  
  776.       stack = ((char *) (malloc (STACK_EXCEPTION_STACK_SIZE)));
  777.       if (stack == ((char *) NULL))
  778.     continue;
  779.       if ((DPMI_set_exception_handler (((unsigned) excp),
  780.                        exception_handler,
  781.                        ((void *)
  782.                     (stack 
  783.                                          + STACK_EXCEPTION_STACK_SIZE))))
  784.       != DOS_SUCCESS)
  785.       {
  786.     free (stack);
  787.     continue;
  788.       }
  789.       stack_exception_fault_stack = ((void *) stack);
  790.     }
  791.     else if ((DPMI_set_exception_handler (((unsigned) excp),
  792.                       exception_handler,
  793.                       ((void *) NULL)))
  794.          != DOS_SUCCESS)
  795.       continue;
  796.     dos_record_interrupt_interception ((excp + NUM_DOS_INTVECT),
  797.                        DPMI_restore_handler);
  798.   }
  799.   fflush (stdout);
  800.   return;
  801. }
  802.  
  803. /* No lambda! foo. */
  804.  
  805. static int
  806. DEFUN (DOS_restore_keyboard, (intno), unsigned intno)
  807. {
  808.   if ((dos_restore_kbd_hook ()) != DOS_SUCCESS)
  809.     return (DOS_FAILURE);
  810.   DOS_keyboard_intercepted_p = false;
  811.   return (DOS_SUCCESS);
  812. }     
  813.  
  814. static void
  815. DEFUN_VOID (DOS_install_interrupts)
  816. {
  817.   scm_int_intercept (DOS_INTVECT_USER_TIMER_TICK, 
  818.                      bios_timer_handler, 
  819.                      256);
  820.   if ((dos_install_kbd_hook ()) == DOS_SUCCESS)
  821.   {
  822.     dos_record_interrupt_interception (DOS_INTVECT_SYSTEM_SERVICES,
  823.                        DOS_restore_keyboard);
  824.     DOS_keyboard_intercepted_p = true;    
  825.   }
  826.   if (under_DPMI_p ())
  827.     DPMI_install_exception_handlers ();
  828.   else
  829.     scm_int_intercept (DOS_INTVECT_KB_CTRL_BREAK,
  830.                control_break_handler,
  831.                256);
  832.   return;
  833. }
  834.  
  835. void
  836. DEFUN_VOID (DOS_restore_interrupts)
  837. {
  838.   int iv;
  839.  
  840.   if (dos_interrupts_initialized_p)
  841.   {
  842.     for (iv = (NUM_DOS_HANDLERS - 1); iv >= 0; iv--)
  843.       if ((dos_interrupt_restoration[iv]) != ((int (*) (unsigned)) NULL))
  844.       {
  845.     (void) ((dos_interrupt_restoration[iv]) (iv));
  846.     dos_interrupt_restoration[iv] = ((int (*) (unsigned)) NULL);
  847.       }
  848.     dos_interrupts_initialized_p = false;
  849.   }
  850.   dos_set_ctrl_c_check_flag (ctrl_c_check_flag);
  851.   return;
  852. }
  853.  
  854. /* Signal Bindings */
  855.  
  856. static void
  857. DEFUN (bind_handler, (signo, handler),
  858.        int signo AND
  859.        Tsignal_handler handler)
  860. {
  861.   if ((signo != 0)
  862.       && ((handler != ((Tsignal_handler) sighnd_stop)))
  863.       && ((current_handler (signo)) == SIG_DFL))
  864.     INSTALL_HANDLER (signo, handler);
  865. }
  866.  
  867. void
  868. DEFUN_VOID (DOS_initialize_signals)
  869. {
  870.   stop_signal_hook = 0;
  871.   subprocess_death_hook = 0;
  872.   initialize_signal_descriptors ();
  873.   bind_handler (SIGINT,        sighnd_control_c);
  874.   bind_handler (SIGTERM,    sighnd_control_g);
  875.   bind_handler (SIGFPE,        sighnd_fpe);
  876.   if ((isatty (STDIN_FILENO)) || option_emacs_subprocess)
  877.     {
  878.       bind_handler (SIGILL,    sighnd_hardware_trap);
  879.       bind_handler (SIGSEGV,    sighnd_hardware_trap);
  880.       bind_handler (SIGABRT,    sighnd_software_trap);
  881.     }
  882.   {
  883.     struct signal_descriptor * scan = signal_descriptors;
  884.     struct signal_descriptor * end = (scan + signal_descriptors_length);
  885.     while (scan < end)
  886.       {
  887.     if (((scan -> flags) & NOCATCH) == 0)
  888.       switch (scan -> action)
  889.         {
  890.         case dfl_terminate:
  891.           bind_handler ((scan -> signo), sighnd_terminate);
  892.           break;
  893.         case dfl_stop:
  894.           bind_handler ((scan -> signo), sighnd_stop);
  895.           break;
  896.         }
  897.     scan += 1;
  898.       }
  899.   }
  900.   DOS_initialize_interrupts();
  901.   DOS_install_interrupts();
  902. }
  903.